#pragma once
#include <string.h>

namespace qb{
namespace base{

//==============================================================================
// Summary:
//     make valueT in range [minT,maxT]
//==============================================================================
template<class T>
T SSScopedToRange(const T& valueT,const T& minT,const T& maxT)
{
	return valueT<minT?minT:(valueT>maxT?maxT:valueT);
}

template<typename TYPE,int NUM>
class SFixedArray{
	int			m_count;
	TYPE		m_array[NUM];
public:
	SFixedArray():m_count(0)
	{
		memset(m_array,0,NUM*sizeof(TYPE));
	}
	SFixedArray(SFixedArray&& fa):
		m_count(fa.m_count)
	{
		memcpy(m_array, fa.m_array, NUM*sizeof(TYPE));
		fa.m_count = 0;
	}
	SFixedArray(const SFixedArray& fa) :
		m_count(fa.m_count)
	{
		memcpy(m_array, fa.m_array, NUM * sizeof(TYPE));
	}
	SFixedArray& operator=(SFixedArray&& fa){
		m_count = fa.m_count;
		memcpy(m_array, fa.m_array, NUM*sizeof(TYPE));
		fa.m_count = 0;
		return *this;
	}
	SFixedArray& operator=(const SFixedArray& fa) {
		m_count = fa.m_count;
		memcpy(m_array, fa.m_array, NUM * sizeof(TYPE));
		return *this;
	}
	void Reset(){m_count=0;};
	void clear(){m_count=0;};
	void Add(const TYPE& t)
	{
		//BASSERTS(m_count<NUM,"SFixedArray is full,m_count:%d,m_capcity=%d",m_count,NUM);
		if(m_count<NUM)
			m_array[m_count++] = t;
	}
	int find(const TYPE& t)const
	{
		for (int i = 0; i < m_count; i++)
			if (m_array[i] == t)
				return i;
		return -1;
	}
	void insert(const TYPE& t,int ipos)
	{
		if(m_count>=NUM)
			return;
		//BASSERTS(ipos>=0 && ipos<=m_count,"");
		for (int i=m_count;i>ipos;i--)
		{
			m_array[i]=m_array[i-1];
		}
		m_array[ipos]=t;
		m_count++;
	}
	int  size()const{return m_count;}
	TYPE& operator[](int ipos){return m_array[ipos];}
	const TYPE& operator[](int ipos) const{return m_array[ipos];}

	TYPE& at(int ipos){return m_array[ipos];}
	const TYPE& at(int ipos) const{return m_array[ipos];}
	TYPE* GetBuffer(){return m_array;}
};
template<class TYPE>
class SimpleArray{
	enum {MIN_CAPCITY=16};
	int			m_capcity;
	int			m_count;
	TYPE*		m_array;
public:
	SimpleArray(int capcity=MIN_CAPCITY):m_capcity(capcity),m_count(0)
	{
		m_capcity = m_capcity<=0?MIN_CAPCITY:m_capcity;
		int bytes = sizeof(TYPE)*(m_capcity+1);
		m_array = (TYPE*)(new char[bytes]);
		memset(m_array,0,bytes);
	}
	~SimpleArray()
	{
		if(m_array)
		{
			for (int i=0;i<m_count;i++)
			{
				TYPE& t = m_array[i];
				t.~TYPE();
			}
			delete [] ((char*)m_array);
			m_array = nullptr;
		}
	};
	int getcapcity()const{return m_capcity;}
	int setcapcity(int capcity)
	{
		// 扩张或者压缩
		if(m_count==m_capcity && capcity<=m_count)
			return m_capcity;

		capcity = capcity<=m_count?m_count:capcity;
		if(capcity<=0)	
			return m_capcity;
		
		int bytes   = sizeof(TYPE)*(capcity+1);
		char* arr = new char[bytes];
		if (m_array)
		{
			int used = m_count*sizeof(TYPE);
			if (used>0)
				memcpy(arr, m_array, used);
			memset(arr + used, 0, bytes - used);
			delete[] m_array;
		}else
			memset(arr, 0, bytes);
		m_array = (TYPE*)arr;
		m_capcity = capcity;
		return capcity;
	}
	void Reset(){
		m_count=0;
		reset_tail();
	};
	void clear(){
		m_count=0;
		reset_tail();
	};

	void append(const TYPE* ar,int count)
	{
		expandto(m_count + count);
		const TYPE* end = ar + count;
		for (; ar < end; ++ar)
			m_array[m_count++] = *ar;
		reset_tail();
	}
	void emplace_back(const TYPE& value){
		expandto(m_count + 1);
		m_array[m_count++] = value;
	}
	void emplace_back(TYPE&& value){
		expandto(m_count + 1);
		m_array[m_count++] = value;
	}
	void Add(const TYPE& t,int count)
	{
		expandto(m_count + count);
		for (int i=0;i<count;i++)
			m_array[m_count++] = t;
		reset_tail();
	}
	void Add(const TYPE& t)
	{
		if(m_count>=m_capcity)
		{
			expand();
		}

		m_array[m_count++] = t;
		reset_tail();
	}
	void insert(const TYPE& t,int ipos)
	{
		if(m_count>=m_capcity)
			expand();

		//BASSERTS(ipos>=0 && ipos<=m_count,"");
		for (int i=m_count;i>ipos;i--)
		{
			m_array[i]=m_array[i-1];
		}

		m_array[ipos]=t;
		m_count++;
		reset_tail();
	}
	void replace(int pos,int len,const TYPE* ar,int size)
	{
		// 将位于pos开始的长度为len的内容替换成长度为size的内容ar
		if (pos + len > m_count)
			len = m_count - pos;
		if(pos<0 || len<0 || pos+len>m_count)
			return;
		if(size>1024)
			return;
		if(size<=0)	
			size =0;
		if(size==len)//直接替换
		{
			for (int i=0;i<size;i++){m_array[pos+i]=ar[i];}
			return;
		}
		int end  = pos+len;
		int left = m_count-end;
		int count= m_count+size-len;
		if(count<=m_capcity)// 现有空间够用,无需分配
		{
			if(left>0)
			{
				if(len<size)
				{
					// 往后搬运末尾数据
					for (int i=m_count-1;i>=end;i--)
					{
						m_array[i+size-len]=m_array[i];
					}
				}else
				{
					// 往前搬运末尾数据
					for (int i=end;i<m_count;i++)
					{
						m_array[i+size-len]=m_array[i];
					}
				}
			}
			// 替换数据
			for (int i=0;i<size;i++)
			{
				m_array[pos+i]=ar[i];
			}
			m_count   +=size-len;
			memset(&m_array[m_count],0,sizeof(TYPE));
			return;
		}

		// 需要重新分配
		int capcity = count+(count-m_capcity)/4;
		TYPE* buf = new TYPE[capcity+1];
		if (pos > 0)
		{
			memcpy(buf, m_array, pos*sizeof(TYPE));
		}
		if (size > 0)
		{
			memcpy(buf + pos, ar, size*sizeof(TYPE));
		}
		if (left > 0)
		{
			memcpy(buf + pos + size, m_array + pos + len, left*sizeof(TYPE));
		}

		memset(buf + count, 0, (capcity + 1-count)*sizeof(TYPE));
		delete [] m_array;
		m_array = buf;
		m_capcity = capcity;
		m_count   = count;
	}
	void push_back(const TYPE& t){Add(t);}
	int  size()const{return m_count;}
	bool empty()const{return m_count<=0;}
	int  find(const TYPE& t)
	{
		for (int i=0;i<m_count;i++)
		{
			if(m_array[i]==t)
				return i;
		}
		return -1;
	}
	bool removeAndShift(int ipos)
	{
		if(ipos<0 || ipos>=m_count)
			return false;
		TYPE value = m_array[ipos];
		for (int i=ipos;i<m_count-1;i++)
		{
			m_array[i]=m_array[i+1];
		}
		memset(&m_array[m_count-1],0,sizeof(TYPE));
		m_count--;


		// 存在疑问
		//for(int i=0;i<m_count;i++)
		//{
		//	BASSERTS(m_array[i]!=value,"");
		//	m_array[i] += m_array[i]>=value?-1:0;
		//}
		return true;
	}
	bool erase(int ipos){return remove(ipos);}
	bool remove(int ipos)
	{
		if(ipos>=0 && ipos<m_count)
		{
			for (int i=ipos;i<m_count-1;i++)
			{
				m_array[i]=m_array[i+1];
			}
			memset(&m_array[m_count-1],0,sizeof(TYPE));
			m_count--;
			return true;
		}
		return false;
	}
	void remove_tail(int ipos)
	{
		ipos = ipos<=0?0:ipos;
		if (ipos < m_count && m_array)
		{
			memset(m_array + ipos, 0, sizeof(TYPE)*(m_count - ipos));
			m_count = ipos;
		}
	}
	int remove_equal()
	{
		// 删除前后相等的，返回删除的个数
		if(size()<=1)
			return 0;
		int count=0;
		TYPE* last = &(at(0));
		for (int i=1;i<size();i++)
		{
			if(memcmp(last,&at(i),sizeof(TYPE))==0)
			{
				remove(i);
				count++;
				i--;
			}else
			{
				last = &at(i);
			}
		}
		return count;
	}
	TYPE& operator[](int ipos){return m_array[ipos];}
	const TYPE& operator[](int ipos) const{return m_array[ipos];}

	TYPE& at(int ipos){return m_array[ipos];}
	const TYPE& at(int ipos) const{return m_array[ipos];}
	const TYPE* GetBuffer()const{return m_array;}
	TYPE* GetBuffer(){return m_array;}

public:
	template<typename OWNER>
	class iterator_base{
	protected:
		OWNER*		m_owner;
		int			m_index;
	public:
		iterator_base(OWNER* owner,int index=-1):m_owner(owner),m_index(index){}
		iterator_base(const iterator_base& rhs):m_owner(rhs.m_owner),m_index(rhs.m_index){}
		iterator_base& operator=(const iterator_base& rhs){m_owner=rhs.m_owner,m_index=rhs.m_index;return *this;}
		bool operator==(const iterator_base& rhs){return m_owner==rhs.m_owner && m_index==rhs.m_index;}
		bool operator!=(const iterator_base& rhs){return m_owner!=rhs.m_owner||m_index!=rhs.m_index;};
		iterator_base& operator++(){
			if(m_owner && m_index>=0)
			{
				m_index++;
				if(m_index>=m_owner->size())
					m_index = -1;
			}
			return *this;
		}
		const TYPE* operator->()const{return &(m_owner->at(m_index));}
		const TYPE& operator*()const{return m_owner->at(m_index);}
	};
	typedef iterator_base<const SimpleArray<TYPE> > const_iterator;
	class iterator : public iterator_base<SimpleArray<TYPE> >
	{
	public:
        iterator(SimpleArray<TYPE>* owner,int index):iterator_base<SimpleArray<TYPE> >(owner,index){}
        TYPE& operator*(){return iterator_base<SimpleArray<TYPE> >::m_owner->at(iterator_base<SimpleArray<TYPE> >::m_index);}
        TYPE* operator->(){return &(iterator_base<SimpleArray<TYPE> >::m_owner->at(iterator_base<SimpleArray<TYPE> >::m_index));}
	};
	
	iterator begin(){return iterator(this,0);}
	iterator end(){return iterator(this,-1);}
	const_iterator begin()const{return const_iterator(this,0);}
	const_iterator end()const{return const_iterator(this,-1);}
protected:
	inline void reset_tail()
	{
		if (m_array && m_count<=m_capcity)
			memset(&m_array[m_count], 0, sizeof(TYPE));
	}
	void expandto(int capcity)
	{
		// 额外增加的1个字节使得用于字符串0强行结尾
		capcity = capcity < MIN_CAPCITY ? MIN_CAPCITY : capcity;
		if (capcity <= m_capcity)
			return;
		int bytes = sizeof(TYPE)*(capcity + 1);
		char* arr = new char[bytes];
		if (m_array)
		{
			memcpy(arr, m_array, m_capcity*sizeof(TYPE));
			memset(arr + m_capcity*sizeof(TYPE), 0, (capcity + 1-m_capcity)*sizeof(TYPE));
			delete[] m_array;
		}
		else
		{
			memset(arr, 0, bytes);
		}
		m_array = (TYPE*)arr;
		m_capcity = capcity;
	}
	void expand()
	{
		expandto(m_capcity + (m_capcity>>1));
	}
};

typedef SimpleArray<int>	  SIntArray;

template<class T>
class UIAutoSet{
	T*		m_variable;
	T		m_end_value;
public:
	UIAutoSet(T* pVariable,const T& init,const T& end):
	m_variable(pVariable),m_end_value(end){
		*m_variable = init;
	}
	~UIAutoSet(){
		*m_variable = m_end_value;
	}
};

}//namespace base;
}//namespace qb;


